using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using System.IO;
using Docuverse.Identicon;

/// <summary>
/// Productionized Identicon handler with PNG memorystream caching
/// </summary>
/// <author>Jeff Atwood http://www.codinghorror.com/, Jon Galloway http://weblogs.asp.net/jgalloway/</author>
public class IdenticonHandler : IHttpHandler
{
  private IdenticonRenderer _renderer = new IdenticonRenderer();

  public void ProcessRequest(HttpContext context)
  {
    if (context == null)
      throw new ArgumentNullException("context", "This handler only applies to Http Requests.");

    HttpRequest request = context.Request;
    HttpResponse response = context.Response;

    int code;
    if (String.IsNullOrEmpty(request["code"]) || !Int32.TryParse(request["code"], out code))
    {
      code = IdenticonUtil.Code(request.UserHostAddress);
    }

    int size;
    if (!int.TryParse(request["size"], out size))
    {
      size = 32;
    }

    string etag = IdenticonUtil.ETag(code, size);
    if (request.Headers["If-None-Match"] == etag)
    {
      // browser already has the image cached
      response.StatusCode = (int)HttpStatusCode.NotModified;
    }
    else
    {
      MemoryStream ms = HttpRuntime.Cache.Get(etag) as MemoryStream;
      // retrieve image bytes from cache or renderer
      if (ms == null)
      {
        ms = new MemoryStream();
        using (Bitmap b = _renderer.Render(code, size))
        {
          b.Save(ms, ImageFormat.Png);
        }
        HttpRuntime.Cache[etag] = ms;
      }
      response.AppendHeader("ETag", etag);
      response.ContentType = "image/png";
      ms.WriteTo(response.OutputStream);
    }
    HttpContext.Current.ApplicationInstance.CompleteRequest();
  }

  public bool IsReusable
  {
    get { return true; }
  }
}